package me.hetong.server;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.extra.ssh.JschUtil;
import cn.hutool.log.StaticLog;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpProgressMonitor;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author hetong
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class TtSSHClient {

    private String ip;
    private int port = 22;
    private String username = "root";
    private String password;

    /**
     * 从指定文件中创建客户端
     * 配置文件中只包含一行，用英文逗号分隔，分别：ip,端口(不传为22),用户名(不传为root),密码
     *
     * @param path 配置文件路径
     * @return
     */
    public static TtSSHClient createFromFile(String path) {
        String s = FileUtil.readLines(path, CharsetUtil.UTF_8).get(0);
        String[] split = s.split(",");
        if (split.length == 2) {
            return new TtSSHClient(split[0], split[1]);
        } else if (split.length == 3) {
            return new TtSSHClient(split[0], split[1], split[2]);
        } else if (split.length == 4) {
            return new TtSSHClient(split[0], Integer.valueOf(split[1]), split[2], split[4]);
        } else {
            StaticLog.error("配置文件错误,{}", path);
        }
        return null;
    }

    public TtSSHClient(String ip, String password) {
        this.ip = ip;
        this.password = password;
    }

    public TtSSHClient(String ip, String username, String password) {
        this.ip = ip;
        this.username = username;
        this.password = password;
    }

    public Session createSession() throws Exception {
        Session session = JschUtil.createSession(ip, port, username, password);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();
        return session;
    }

    public void executeCmd(String cmd) {
        StaticLog.info("开始执行脚本");
        Session session = null;
        ChannelExec channel = null;
        try {

            session = this.createSession();
            channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(cmd);
            channel.setInputStream(null);

            // 获取命令执行结果
            channel.setErrStream(System.err);

            InputStream ins = channel.getInputStream();
            channel.connect();

            // 打印输出结果
            byte[] tmp = new byte[]{};
            while (true) {
                while (ins.available() > 0) {
                    int i = ins.read(tmp, 0, 1024);
                    if (i < 0) {
                        break;
                    }
                    StaticLog.info(new String(tmp, 0, i));
                }
                if (channel.isClosed()) {
                    if (ins.available() > 0) {
                        continue;
                    }
                    StaticLog.info("Exit status: " + channel.getExitStatus());
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        } catch (JSchException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (channel != null) {
                channel.disconnect();
            }
            session.disconnect();
        }

        StaticLog.info("执行脚本完成");
    }


    /**
     * 上传文件
     */
    public void upload(String sourceFileAbsolutePath, String targetFoldAbsolutePath) {
        Session session = null;

        try {

            session = this.createSession();
            ChannelSftp channel = (ChannelSftp) session.openChannel("sftp");
            channel.connect();

            File file = new File(sourceFileAbsolutePath);
            long total = file.length();

            SftpProgressMonitor sftpProgressMonitor = new SftpProgressMonitor() {

                private long transferredBytes = 0L;

                @Override
                public void init(int i, String s, String s1, long l) {
                    StaticLog.info("初始化: 从 {} 上传到 {} (文件大小: {})", sourceFileAbsolutePath, targetFoldAbsolutePath, total);
                }

                @Override
                public boolean count(long l) {
                    transferredBytes += l;
                    int percentComplete = (int) (transferredBytes * 100L / total);

                    StaticLog.info("已上传 {}/{} 字节 {}%", transferredBytes, total, percentComplete);
                    // 返回true以继续传输，或false以取消
                    return true;
                }

                @Override
                public void end() {
                    StaticLog.info("上传成功,源文件:{},目标位置:{}", sourceFileAbsolutePath, targetFoldAbsolutePath);
                }
            };

            // 使用进度跟踪上传文件
            channel.put(sourceFileAbsolutePath, targetFoldAbsolutePath, sftpProgressMonitor);

            channel.exit();
            session.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 确保session被关闭（如果有的话）
            if (session != null) {
                session.disconnect();
            }
        }
    }

    public static void main(String[] args) {
        TtSSHClient client = TtSSHClient.createFromFile("/Users/*/Library/Mobile Documents/com~apple~CloudDocs/mm/person/script/damh-prod.txt");
        client.upload("/Users/hetong/local/code/damh/damh-dsp-new/target/dsp.jar", "/home/app");
        client.executeCmd("cd /home/app;sh backup.sh dsp.jar;sh startup.sh dsp.jar 7788");
    }
}
